/* 
 * protocol.h -- Constants and types required by the A664P7 over Ethernet library
 *               to implement A664P7/UDP/IP protocol
 *
 *
 *------------------------------------------------------------------------------
 *
 *                    ---   PROPRIETARY NOTICE   ---
 *
 *   The information contained herein is proprietary to Smiths Aerospace.
 *   and shall not be reproduced or disclosed in whole or in part or used
 *   for any design or manufacture except when such user possesses direct
 *   written authorization from Smiths Aerospace.
 *
 *   Copyright 2006, Smiths Aerospace.
 *
 *------------------------------------------------------------------------------
 *
 * modification history
 * --------------------
 * 30 mar 06	Huizenga	Initial revision.
 * 02 jun 06	Huizenga	Fixed size of rm seq. num (16 bit -> 8 bit)
 * 05 jun 06	Huizenga	Added new comments for PACKET and VL structures
 */

#ifndef __INCLUDE_PROTOCOL_H__
#define __INCLUDE_PROTOCOL_H__

#include "pcap.h"

#if !defined BIG_ENDIAN
  #define BIG_ENDIAN    4321
#endif
#if !defined LITTLE_ENDIAN
  #define LITTLE_ENDIAN 1234
#endif

/* if BYTE_ORDER is undefined, guess LITTLE_ENDIAN since i386 is very common*/
#if !defined BYTE_ORDER
	#define BYTE_ORDER LITTLE_ENDIAN
#endif

typedef unsigned char MAC_ADDRESS [6];

typedef struct ETHERNET_HEADER {
	MAC_ADDRESS	dest;
	MAC_ADDRESS	source;
	unsigned short int	type;			
} ETHERNET_HEADER;

#define	ETH_TYPE_IP	0x0800

#define PROT_ICMP 0x01
#define PROT_TCP 0x06
#define PROT_UDP 0x11

typedef struct IP_HEADER {
#if BYTE_ORDER == LITTLE_ENDIAN
	unsigned char		hl  : 4;		/* The order of these two bitfields (ver / IHL) */
    unsigned char		ver : 4;		/* is dependant upon the endianess of the machine */
#else
    unsigned char		ver : 4;		
	unsigned char 		hl  : 4;
#endif
    unsigned char		tos;				/* Type of Service (not used) / set to 0 */
    unsigned short int  len;				/* Total length */
    unsigned short int  id;					/* Fragment ID (should always be set to a unique #) */
	unsigned short int  rsvd_flag		: 1;	/* Unused flag */
	unsigned short int  dont_frag		: 1;	/* "Done Fragment" flag */
	unsigned short int  more_frag		: 1;	/* "More Fragments" flag */
    unsigned short int  frag_off		: 13;	/* Fragmetn offest */
    unsigned char		ttl;				/* Time To Live */
    unsigned char		protocol;			/* Protocal ID (UDP = 0x11) */
    unsigned short int  check;				/* Checksum (auto-set by send() calls) */
    unsigned int		src;				/* Source IP */
    unsigned int		dst;				/* Dest. IP */
} IP_HEADER;

typedef struct UDP_HEADER {
	unsigned short int	s_port;
	unsigned short int	d_port;
	unsigned short int	length;			// including this header
	unsigned short int	check;
} UDP_HEADER;

typedef struct PACKET {
	ETHERNET_HEADER *eh;		/* Points to the ethernet header within the data buffer */
	IP_HEADER *ih;				/* Points to the IP header within the data buffer */
	UDP_HEADER *uh;				/* Points to the UDP header within the data buffer */
	char *buf;					/* Pointer to the data buffer */
	char *data;					/* Pointer to the payload within the data buffer */
	unsigned char *rm_seq_num;  /* Points to the rm sequence number within the data buffer */
	int data_length;			/* Amount of payload data buffer space that is in use (INCLUDING pad) */
								/* This will be equal to the UDP payload length for messages >= 17 bytes, otherwise
								 * it will be equal to 17 bytes, due to the required minimum frame size of 60 bytes */
	int data_buffer_length;		/* Amount of buffer space that was allocated for payload when the packet was created */
	int buffer_length;			/* Total amount of buffer space that was allocated when the packet was created
	                             * (including headers, payload, & seq. num) */
	int packet_header_byte_order; /* indicates if headers (including rm seq num) are net order or host order */
} PACKET;

/* Bitfield flags for VL packet matching */
#define VL_PKT_MATCH       0
#define VL_PHYS_INTERFACE  1
#define VL_LENGTH          2
#define VL_DEST_MAC        4
#define VL_IP_CHECK        8
#define VL_IP_PROTO        16
#define VL_IP_VER          32
#define VL_IP_LEN          64
#define VL_IP_ADDR         128
#define VL_UDP_PORT        256

/* Packet order flags */
#define PACKET_ORDER_HOST 0
#define PACKET_ORDER_NET 1

/* Fragmentation isn't supported, so the max IP packet size is equal 
	to the max ethernet frame size */
#define MAX_PACKET_SIZE 1518
#define RM_SEQ_NUM_LEN 1

/* Constants for the VL structure's new_message bitfield */
#define VL_RX_NEW 1
#define VL_TX_NEW 2

typedef struct VL {
	PACKET *pkt;				/* A pointer to the PACKET in which this VL's messages will be built */
	int vl_num;					/* Stores the VL's number */
	unsigned char rm_seq_num;	/* Stores the current sequence number for the VL (used for tx VLs) */
	int vl_mode;				/* Stores the tx/rx mode for this VL */
	int new_message;			/* Indicates the presence of newly received (rxVLs) or freshly written (txVLs) messages */
	pcap_t *net_a_dev;			/* Handle for the Network A interface */
	pcap_t *net_b_dev;			/* Handle for the Network B interface */
} VL;

/* Singly-linked list used by the VL layer to keep track of all user-created VLs */
typedef struct VL_LIST 
{
	VL *vl;
	struct VL_LIST *next_vl;
} VL_LIST;

/* Used by the VL layer to keep track of all devices associated with user-created VLs */
typedef struct VL_DEVICE_LIST {
	pcap_t *dev;
	struct VL_DEVICE_LIST *next_dev;
} VL_DEVICE_LIST;

#endif